package com.cn.rpcframe.rpcproxy;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.codec.LengthFieldPrepender;
import io.netty.handler.codec.serialization.ClassResolvers;
import io.netty.handler.codec.serialization.ObjectDecoder;
import io.netty.handler.codec.serialization.ObjectEncoder;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import com.cn.rpcframe.entity.ClassInfo;
import com.cn.rpcframe.network.ResultHandler;
import com.cn.rpcframe.registeranddiscover.ServiceRegisterAndDiscovery;
import com.cn.rpcframe.zookeeperoperation.ZookeeperServicImpl;

public class RpcProxy {
	ServiceRegisterAndDiscovery serviceDiscovery =null;
	
	 @SuppressWarnings("unchecked")  
	    public   <T> T create(  Class<T> target){  
		 return (T) Proxy.newProxyInstance(RpcProxy.class.getClassLoader(),new Class<?>[]{target}, new InvocationHandler(){

			@Override
			public Object invoke(Object proxy, Method method, Object[] args)
					throws Throwable {
				// TODO Auto-generated method stub
				 ClassInfo classInfo = new ClassInfo();  
	             classInfo.setClassName(method.getDeclaringClass().getName());  
	             classInfo.setMethodName(method.getName());  
	             classInfo.setObjects(args);  
	             classInfo.setTypes(method.getParameterTypes());  
	             final ResultHandler resultHandler = new ResultHandler();  
	             EventLoopGroup group = new NioEventLoopGroup(); 
				 try{
					  Bootstrap b = new Bootstrap();    
	                  b.group(group).channel(NioSocketChannel.class)
	                  .option(ChannelOption.TCP_NODELAY, true)
	                  .handler(new ChannelInitializer<SocketChannel>(){

						@Override
						protected void initChannel(SocketChannel ch)
								throws Exception {
							// TODO Auto-generated method stub
							  ChannelPipeline pipeline = ch.pipeline();    
	                             pipeline.addLast("frameDecoder", new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 4, 0, 4));    
	                             pipeline.addLast("frameEncoder", new LengthFieldPrepender(4));    
	                             pipeline.addLast("encoder", new ObjectEncoder());      
	                             pipeline.addLast("decoder", new ObjectDecoder(Integer.MAX_VALUE, ClassResolvers.cacheDisabled(null)));    
	                             pipeline.addLast("handler",resultHandler);  
						}
	                	  
	                  });
	                  //从 zookeeper中取出 对应的服务名字 和服务地址
	                  if(serviceDiscovery ==null){
	                	  serviceDiscovery = new ZookeeperServicImpl("127.0.0.1:2181");
	                  }
	                  String hostAndPort = serviceDiscovery.discovery(classInfo.getClassName());
	                  String[] host = hostAndPort.split("-");
	                  ChannelFuture future = b.connect(host[1], Integer.parseInt(host[2])).sync();    
	                    future.channel().writeAndFlush(classInfo).sync();  
	                    future.channel().closeFuture().sync();   
				 }catch(Exception e){
					 e.printStackTrace();
				 }finally {    
	                    group.shutdownGracefully();    
	                }  
	                return resultHandler.getResponse();
	                
	                
				     
			}
			 
		 });
	 }
}
